import moment from 'moment';

export default class timeAxis {
  constructor(options) {
    if (!options.dom) {
      return '';
    }
    for (let option in options) {
      if (options.hasOwnProperty(option)) {
        this[option] = options[option]
      }
    }
    if (this.timecell && this.timecell.length) {
      this.currentTimestamp = this.timecell[0].begin
    }
    if (options.cellStyle && options.cellStyle.background) {
      this.cellStyle = options.cellStyle
    } else {
      this.cellStyle = {
        background: 'rgba(24,208,217,0.5)'
      }
    }
    this.isClick = false

    this.button = 0;// 0:左键， 2:右键
    this.isPressDown = false; // 是否按下
    this.isDragPointer = false;
    this.currentChecked = '';

    this.zoomHours = 24;
    this.graduationMinStep = 10;
    this.minutesPerStep = [1, 2, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440];
    this.pointerOptions = {
      beginX: 0,
      beginY: 0,
      endX: 0,
      endY: 30,
      color: "rgb(64, 196, 255)",
      width: 2
    };
    this.initCanvas();
    this.initCanvasCtx();
  }

  initCanvas() {
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.dom.clientWidth;
    this.canvas.height = this.dom.clientHeight;
    this.canvas.style.backgroundColor = this.bg;
    this.canvasWidth = this.canvas.width;
    this.canvasHeight = this.canvas.height;
    this.dom.appendChild(this.canvas);

    this.canvasCtx = this.canvas.getContext("2d");
    this.canvasGraduationsLinesCtx = this.canvas.getContext("2d");
    this.canvasPlayPointerCtx = this.canvas.getContext("2d");
    this.initEvents()
  }

  resize() {
    this.canvas.width = this.dom.clientWidth;
    this.canvas.height = this.height;
    this.canvas.style.backgroundColor = this.bg;
    this.canvasWidth = this.canvas.width;
    this.canvasHeight = this.canvas.height;
    this.clearCanvas();
    this.initCanvasCtx()
  }

  initCanvasCtx() {
    this.pxPerMs = (this.canvasWidth) / (this.zoomHours * 60 * 60 * 1000);
    this.initBorders();
    this.initTimeCells(this.timecell || []);

    // 渲染时间轴
    this.initGraduationsLines(this.date);

    if (this.isClick) {
      // 渲染播放指针
      this.initPlayPointerCtx();
    }
  }

  // 初始化边框
  initBorders() {
    let borderColor = "rgb(151, 158, 167)";
    //顶线
    this.drawLine({
      beginX: 0,
      beginY: 0,
      endX: this.canvasWidth,
      endY: 0,
      color: borderColor,
      width: 1
    });
    //底线
    this.drawLine({
      beginX: 0,
      beginY: this.canvasHeight,
      endX: this.canvasWidth,
      endY: this.canvasHeight,
      color: borderColor,
      width: 1
    });
  }

  // 画线
  drawLine({beginX, beginY, endX, endY, color, width}) {
    this.canvasCtx.beginPath();
    this.canvasCtx.moveTo(beginX, beginY);
    this.canvasCtx.lineTo(endX, endY);
    this.canvasCtx.strokeStyle = color;
    this.canvasCtx.lineWidth = width;
    this.canvasCtx.stroke();
  }

  // 有效时间区域
  initTimeCells(datas) {
    // 分段填充时间段
    datas.forEach((cell, index) => {
      this.drawCell(cell, index)
    });
    this.canvasCtx.font = 'normal normal 12px Arial,sans-serif';
    this.canvasCtx.fillStyle = '#fff';
  }

  // 填充时间段
  drawCell(data, index) {
    let fillColor = this.cellStyle.background
    if (data.style && data.style.background) {
      fillColor = data.style.background
    }
    let cellBeginX = this.pxPerMs * (data.begin - this.date);
    let cellWidth = (data.end - data.begin) * this.pxPerMs;
    this.canvasCtx.fillStyle = fillColor;
    this.canvasCtx.font = 'normal normal 12px Arial,sans-serif';
    this.canvasCtx.fillRect(cellBeginX, 0, cellWidth, this.canvas.height);
    this.canvasCtx.fillStyle = '#fff';
  }

  // 初始化刻度线
  initGraduationsLines(date) {
    let widthTotal = this.canvasWidth;
    // 一分钟转换为px
    let pxPerMinute = widthTotal / (this.zoomHours * 60);
    // 一毫秒转换为px
    let pxPerMs = widthTotal / (this.zoomHours * 60 * 60 * 1000);
    // 一格转换为分钟
    let StepPerMinute = this.graduationMinStep / pxPerMinute;
    let minutePerStep = this.minutesPerStep.find(item => item > StepPerMinute);
    // 每格的宽度
    let stepPerPx = minutePerStep * pxPerMinute;
    //总格数(每格{minutePerStep}分钟)
    let stepTotalNum = widthTotal / stepPerPx;

    let msOffset = this.ms_to_next_step(date, minutePerStep * 60 * 1000);//开始的偏移时间 ms
    let pxOffset = msOffset * pxPerMs; //开始的偏移距离 px

    for (let i = 0; i <= stepTotalNum; i++) {
      let graduationTime = date + msOffset + i * (stepPerPx / pxPerMs); //时间=左侧开始时间+偏移时间+格数*ms/格
      let leftPx = pxOffset + i * stepPerPx;
      let lineH = 10;
      let width = 1;
      if (this.formatDate('hh:mm:ss', graduationTime) === '00:00:00') {
        // 0点
        lineH = 20;
        width = 3;
        let bigDateTitle = this.formatDate('MM-dd', graduationTime);
        this.canvasGraduationsLinesCtx.textAlign = 'center';
        this.canvasGraduationsLinesCtx.fillStyle = "#ffffff";
        this.canvasGraduationsLinesCtx.font = 'normal normal 12px Arial,sans-serif';
        this.canvasGraduationsLinesCtx.fillText(bigDateTitle, leftPx, 30);
      } else if (graduationTime / (60 * 6 * 1000) % minutePerStep === 0) {
        // 整小时
        lineH = 15;
        width = 2;
        let middleDateTitle = this.formatDate('hh:mm', graduationTime);
        this.canvasGraduationsLinesCtx.fillStyle = "#ffffff";
        this.canvasGraduationsLinesCtx.textAlign = 'center';
        this.canvasGraduationsLinesCtx.font = 'normal normal 12px Arial,sans-serif';
        this.canvasGraduationsLinesCtx.fillText(middleDateTitle, leftPx, 25);
      } else {
        lineH = 10;
        width = 1;
      }
      let options = {
        beginX: leftPx,
        beginY: 0,
        endX: leftPx,
        endY: lineH,
        color: "rgba(151,158,167,1)",
        width: 1
      };
      // 刻度线
      this.drawLine(options);
    }
  }

  // 初始化指针
  initPlayPointerCtx() {
    if (this.currentTimestamp) {
      this.pointerOptions.beginX = this.pxPerMs * (this.currentTimestamp - this.date)
      this.pointerOptions.endX = this.pxPerMs * (this.currentTimestamp - this.date)
    }
    this.canvasPlayPointerCtx.beginPath();
    // 开始位置 (0,0)
    this.canvasPlayPointerCtx.moveTo(this.pointerOptions.beginX, this.pointerOptions.beginY);
    // 结束位置 (0,30)
    this.canvasPlayPointerCtx.lineTo(this.pointerOptions.endX, this.pointerOptions.endY);
    this.canvasPlayPointerCtx.strokeStyle = this.pointerOptions.color;
    this.canvasPlayPointerCtx.lineWidth = this.pointerOptions.width;
    this.canvasPlayPointerCtx.stroke();
    // 三角箭头
    this.canvasPlayPointerCtx.beginPath();
    let height = 12 / Math.sin(Math.PI / 3.5);//计算等边三角形的高
    this.canvasPlayPointerCtx.moveTo(this.pointerOptions.beginX, this.pointerOptions.endY - 1); //从A（100,0）开始
    this.canvasPlayPointerCtx.lineTo((this.pointerOptions.beginX) - (height / 2), 40);//从A(100,0)开始，画到B (0,173)结束
    this.canvasPlayPointerCtx.lineTo((this.pointerOptions.beginX) + (height / 2), 40); //B(0,173)-C(200,173)
    // ctx.fillStyle='#00ff00';//以纯色绿色填充
    let grd = this.canvasPlayPointerCtx.createLinearGradient(0, 0, 200, 0);//使用渐变颜色填充,从(0,0)到(200,0) （左到右）
    grd.addColorStop(0, this.pointerOptions.color); //起始颜色
    grd.addColorStop(1, this.pointerOptions.color); //终点颜色
    this.canvasPlayPointerCtx.fillStyle = grd; //以上面定义的渐变填充
    this.canvasPlayPointerCtx.fill(); //闭合形状并且以填充方式绘制出来
    this.canvasPlayPointerCtx.closePath();
  }

  ms_to_next_step(timestamp, step) {
    let remainder = timestamp % step;
    return remainder ? step - remainder : 0;
  }

  // 注册事件
  initEvents() {
    if (this.canvas) {
      this.canvas.addEventListener('contextmenu', (e) => {
        e.preventDefault();
      });
      this.canvas.addEventListener('mousemove', this.canvasMousemoveFunc.bind(this));
      // 滚轮事件
      this.canvas.addEventListener('mousewheel', this.mousewheelFunc.bind(this));
      this.canvas.addEventListener('mousedown', this.mousedownFunc.bind(this));
      this.canvas.addEventListener('mouseup', this.mouseupFunc.bind(this));
      this.canvas.addEventListener('mouseout', this.mouseoutFunc.bind(this));

      this.canvas.addEventListener('click', this.clickFunc.bind(this));
    }
  }

  // 判断能否拖动轴
  canDragAxis() {

  }

  canDragPointer(ev) {
    let x = ev.offsetX;
    let y = ev.offsetY;
    return this.canvasPlayPointerCtx.isPointInPath(x, y)
  }

  setPointer(ev) {
    if (this.canDragPointer(ev)) {
      this.dom.style.cursor = 'pointer';
      this.isDragPointer = true
      this.isMoveTriangle = true
    } else if (!this.isPressDown || this.button) {
      // 指针没在拖动过程中
      if (!(this.isPressDown && this.isMoveTriangle)) {
        this.isDragPointer = false;
        this.isMoveTriangle = false;
        this.dom.style.cursor = '';
      }
    }
  }

  // 鼠标点击(按下)
  mousedownFunc(e) {
    if (e.button === 0) {
      // 左键按下
      this.isPressDown = true;
      this.button = e.button;

      if (this.canDragPointer(e)) {
        this.currentChecked = 'pointer'
      } else {
        this.currentChecked = 'axis'
      }

      // 鼠标移动事件
      document.onmousemove = (e) => {
        this.mousemoveFunc(e)
      }
      document.onmouseup = (e) => {
        this.mouseupFunc(e)
        document.onmousemove = null
        document.onmouseup = null
      }

      this.isDown = true;
      this.g_mousedownCursor = this.getCursorPositionX(e);// 记住mousedown的位置
    } else if (e.button === 2) {
      // 右键按下

    }
  }

  // canvas 鼠标移动
  canvasMousemoveFunc(e) {
    let posX = this.getCursorPositionX(e);
    this.setPointer(e)
    this.clearCanvas();
    // 只鼠标移动
    let timestamp = this.date + posX / this.pxPerMs;
    if (!this.isMoveTriangle) {
      this.drawLine({
        beginX: posX,
        beginY: 0,
        endX: posX,
        endY: this.canvasHeight,
        color: "rgb(194, 202, 215)",
        width: 1
      });
    }
    this.initCanvasCtx();
    this.canvasCtx.fillStyle = "rgb(0, 255, 0)";
    this.canvasCtx.textAlign = 'center';
    this.canvasCtx.fillText(this.formatDate('yyyy-MM-dd hh:mm:ss', timestamp), posX, 18);
  }

  // 鼠标移动
  mousemoveFunc(e) {
    let posX = this.getCursorPositionX(e);
    this.setPointer(e)
    this.clearCanvas();
    this.isMove = true;

    if (this.currentChecked === 'axis') {
      // 拖动时间轴
      let diffX = posX - this.g_mousedownCursor;
      this.date = this.date - Math.round(diffX / this.pxPerMs);
      this.g_mousedownCursor = posX;
      this.initCanvasCtx();
    } else if (this.currentChecked === 'pointer') {
      this.currentTimestamp = this.date + posX / this.pxPerMs;
      this.g_mousedownCursor = posX;
      this.initCanvasCtx();
      this.canvasCtx.fillStyle = "rgb(0, 255, 0)";
      this.canvasCtx.textAlign = 'center';
      this.canvasCtx.fillText(this.formatDate('yyyy-MM-dd hh:mm:ss', this.currentTimestamp), posX, 18);
    }
  }

  // 鼠标抬起
  mouseupFunc(e) {
    if (this.isPressDown && this.button === 0) {
      // 左键
      this.isPressDown = false;
      if (this.isMove) {
        // 拖动
        this.isMove = false;
        if (this.currentChecked === 'axis') {
          // 拖动轴
        } else if (this.currentChecked === 'pointer') {
          // 拖动指针
          this.returnTime = this.currentTimestamp;
          this.returnCheckTime('darg', this.returnTime);
        }
        this.currentChecked = '';
      } else {
        // 点击
        if (!this.isClick) {
          this.isClick = true
        }
        let posX = this.getCursorPositionX(e);
        this.currentTimestamp = this.returnTime = this.date + posX * (this.zoomHours * 3600 * 1000) / (this.canvasWidth);
        this.returnCheckTime('click', this.returnTime);
        this.clearCanvas();
        this.initCanvasCtx();
      }
    }
  }

  // 鼠标点击
  clickFunc(e) {
  }

  // 滚轮事件
  mousewheelFunc(event) {
    if (event && event.preventDefault) {
      event.preventDefault()
    } else {
      window.event.returnValue = false;
      return false;
    }
    let e = window.event || event;
    let delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
    let posX = this.getCursorPositionX(e);
    let middle_time = this.date + posX * (this.zoomHours * 3600 * 1000) / (this.canvasWidth); //ms 记住当前中间的时间
    if (delta < 0) {
      this.zoomHours = this.zoomHours - delta;
      if (this.zoomHours >= 24) {
        this.zoomHours = 24;//放大最大24小时
      }
    } else if (delta > 0) {// 放大
      this.zoomHours = this.zoomHours - delta;
      if (this.zoomHours <= 1) {
        this.zoomHours = 1;//缩小最小1小时
      }
    }
    this.clearCanvas();
    this.date = middle_time - posX * (this.zoomHours * 3600 * 1000) / (this.canvasWidth);
    this.initCanvasCtx()
  }

  mouseoutFunc(e) {
    this.clearCanvas();
    this.initCanvasCtx()
  }

  // 鼠标指针X位置
  getCursorPositionX(e) {
    let posx = 0;
    if (!e) {
      e = window.event;
    }
    if (e.pageX || e.pageY) {
      posx = e.pageX;
    } else if (e.clientX || e.clientY) {
      posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
    }
    posx -= (this.canvas.getBoundingClientRect().left);
    return posx;
  }

  // 清除canvas 每次重新绘制需要先清除
  clearCanvas() {
    this.canvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
  }

  /**
   * 返回点击或者拖动的时间点
   * @param handle 触发方式{click,darg}
   * @param currentTime 选中时间戳{1637164800000}
   */
  returnCheckTime(handle, currentTime) {
    // 向下取整
    let formatCurrentTime = Math.floor(currentTime);
    // 判断时间是否有效
    let isIndex = this.timecell.findIndex(item => {
      return formatCurrentTime >= item.begin && formatCurrentTime <= item.end;
    });
    if (isIndex >= 0) {
      // 有效区域
      if (handle === 'darg') {
        this.callback({
          mode: 'darg', // 触发方式
          timestamp: formatCurrentTime, // 时间戳
          valid: true // 是否有效
        })
      } else if (handle === 'click') {
        this.callback({
          mode: 'click',
          timestamp: formatCurrentTime,
          valid: true
        })
      }
    } else {
      // 无效区域
      this.callback({
        mode: 'click',
        timestamp: formatCurrentTime,
        valid: false
      })
    }
  }

  formatDate(fmt, date) {
    let myDate = date ? new Date(date) : new Date();
    fmt = fmt || 'yyyy-MM-dd';
    const o = {
      'M+': myDate.getMonth() + 1, // 月份
      'd+': myDate.getDate(), // 日
      'h+': myDate.getHours(), // 小时
      'm+': myDate.getMinutes(), // 分
      's+': myDate.getSeconds(), // 秒
      'q+': Math.floor((myDate.getMonth() + 3) / 3), // 季度
      'S': myDate.getMilliseconds() // 毫秒
    };
    if (/(y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (myDate.getFullYear() + '').substr(4 - RegExp.$1.length))
    }
    for (const k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
      }
    }
    return fmt
  }

  updateDatas(options) {
    this.zoomHours = options.zoomHours
    this.date = options.date
    this.timecell = options.times
    if (options.times.length) {
      // this.currentTimestamp = options.times[0].begin
    }
    this.clearCanvas();
    this.initCanvasCtx()
  }

  // 更新时间 m
  updateTime(time) {
    if (this.returnTime) {
      this.returnTime = time
      this.currentTimestamp = time
    }
    this.clearCanvas();
    this.initCanvasCtx()
  }
}
